package com.ruoyi.energy.service.impl;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.energy.mapper.EmsDeviceMapper;
import com.ruoyi.energy.domain.EmsDevice;
import com.ruoyi.energy.service.IEmsDeviceService;

/**
 * 设备管理Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-01-20
 */
@Service
public class EmsDeviceServiceImpl implements IEmsDeviceService {
    
    @Autowired
    private EmsDeviceMapper emsDeviceMapper;

    /**
     * 查询设备
     * 
     * @param deviceId 设备主键
     * @return 设备
     */
    @Override
    public EmsDevice selectEmsDeviceByDeviceId(Long deviceId) {
        return emsDeviceMapper.selectEmsDeviceByDeviceId(deviceId);
    }

    /**
     * 查询设备列表
     * 
     * @param emsDevice 设备
     * @return 设备
     */
    @Override
    public List<EmsDevice> selectEmsDeviceList(EmsDevice emsDevice) {
        return emsDeviceMapper.selectEmsDeviceList(emsDevice);
    }

    /**
     * 新增设备
     * 
     * @param emsDevice 设备
     * @return 结果
     */
    @Override
    public int insertEmsDevice(EmsDevice emsDevice) {
        // 校验设备编码唯一性
        if (!checkDeviceCodeUnique(emsDevice)) {
            throw new ServiceException("新增设备'" + emsDevice.getDeviceName() + "'失败，设备编码已存在");
        }
        
        // 校验能源类型和相关参数
        validateEnergyTypeAndParams(emsDevice);
        
        emsDevice.setCreateBy(SecurityUtils.getUsername());
        emsDevice.setCreateTime(DateUtils.getNowDate());
        return emsDeviceMapper.insertEmsDevice(emsDevice);
    }

    /**
     * 修改设备
     * 
     * @param emsDevice 设备
     * @return 结果
     */
    @Override
    public int updateEmsDevice(EmsDevice emsDevice) {
        // 校验设备编码唯一性
        if (!checkDeviceCodeUnique(emsDevice)) {
            throw new ServiceException("修改设备'" + emsDevice.getDeviceName() + "'失败，设备编码已存在");
        }
        
        // 校验能源类型和相关参数
        validateEnergyTypeAndParams(emsDevice);
        
        emsDevice.setUpdateBy(SecurityUtils.getUsername());
        emsDevice.setUpdateTime(DateUtils.getNowDate());
        return emsDeviceMapper.updateEmsDevice(emsDevice);
    }

    /**
     * 批量删除设备
     * 
     * @param deviceIds 需要删除的设备主键
     * @return 结果
     */
    @Override
    public int deleteEmsDeviceByDeviceIds(Long[] deviceIds) {
        return emsDeviceMapper.deleteEmsDeviceByDeviceIds(deviceIds);
    }

    /**
     * 删除设备信息
     * 
     * @param deviceId 设备主键
     * @return 结果
     */
    @Override
    public int deleteEmsDeviceByDeviceId(Long deviceId) {
        return emsDeviceMapper.deleteEmsDeviceByDeviceId(deviceId);
    }

    /**
     * 校验设备编码是否唯一
     * 
     * @param device 设备信息
     * @return 结果
     */
    @Override
    public boolean checkDeviceCodeUnique(EmsDevice device) {
        Long deviceId = StringUtils.isNull(device.getDeviceId()) ? -1L : device.getDeviceId();
        EmsDevice info = emsDeviceMapper.selectEmsDeviceByDeviceCode(device.getDeviceCode());
        if (StringUtils.isNotNull(info) && info.getDeviceId().longValue() != deviceId.longValue()) {
            return false;
        }
        return true;
    }

    /**
     * 根据部门ID查询设备列表
     * 
     * @param deptId 部门ID
     * @return 设备集合
     */
    @Override
    public List<EmsDevice> selectEmsDeviceListByDeptId(Long deptId) {
        return emsDeviceMapper.selectEmsDeviceListByDeptId(deptId);
    }

    /**
     * 根据设备编码查询设备
     * 
     * @param deviceCode 设备编码
     * @return 设备
     */
    @Override
    public EmsDevice selectEmsDeviceByDeviceCode(String deviceCode) {
        return emsDeviceMapper.selectEmsDeviceByDeviceCode(deviceCode);
    }

    /**
     * 导入设备数据
     * 
     * @param deviceList 设备数据列表
     * @param isUpdateSupport 是否更新支持
     * @param operName 操作用户
     * @return 结果
     */
    @Override
    public String importDevice(List<EmsDevice> deviceList, Boolean isUpdateSupport, String operName) {
        if (StringUtils.isNull(deviceList) || deviceList.size() == 0) {
            throw new ServiceException("导入设备数据不能为空！");
        }
        
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        
        for (EmsDevice device : deviceList) {
            try {
                processImportDevice(device, isUpdateSupport, operName);
                successNum++;
                successMsg.append("<br/>" + successNum + "、设备 " + device.getDeviceName() + " 导入成功");
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、设备 " + device.getDeviceName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
            }
        }
        
        return buildImportResult(successNum, failureNum, successMsg, failureMsg);
    }

    /**
     * 处理单个设备导入
     */
    private void processImportDevice(EmsDevice device, Boolean isUpdateSupport, String operName) {
        // 验证必填字段
        validateDeviceRequired(device);
        
        // 查询设备是否存在
        EmsDevice existDevice = emsDeviceMapper.selectEmsDeviceByDeviceCode(device.getDeviceCode());
        
        if (StringUtils.isNull(existDevice)) {
            device.setCreateBy(operName);
            device.setCreateTime(DateUtils.getNowDate());
            this.insertEmsDevice(device);
        } else if (isUpdateSupport) {
            device.setDeviceId(existDevice.getDeviceId());
            device.setUpdateBy(operName);
            device.setUpdateTime(DateUtils.getNowDate());
            this.updateEmsDevice(device);
        } else {
            throw new ServiceException("设备编码已存在");
        }
    }

    /**
     * 验证设备必填字段
     */
    private void validateDeviceRequired(EmsDevice device) {
        if (StringUtils.isEmpty(device.getDeviceCode())) {
            throw new ServiceException("设备编码不能为空");
        }
        if (StringUtils.isEmpty(device.getDeviceName())) {
            throw new ServiceException("设备名称不能为空");
        }
    }

    /**
     * 构建导入结果信息
     */
    private String buildImportResult(int successNum, int failureNum, 
                                   StringBuilder successMsg, StringBuilder failureMsg) {
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 校验能源类型和相关参数
     */
    private void validateEnergyTypeAndParams(EmsDevice device) {
        if (StringUtils.isEmpty(device.getEnergyType())) {
            throw new ServiceException("能源类型不能为空");
        }
        
        String energyType = device.getEnergyType();
        
        // 验证能源类型有效性
        if (!"1".equals(energyType) && !"2".equals(energyType) && !"3".equals(energyType)) {
            throw new ServiceException("能源类型无效，支持：1=电力，2=水力，3=燃气");
        }
        
        // 根据能源类型验证相应参数
        switch (energyType) {
            case "1": // 电力设备
                validateElectricParams(device);
                break;
            case "2": // 水力设备
                validateWaterParams(device);
                break;
            case "3": // 燃气设备
                validateGasParams(device);
                break;
        }
    }
    
    /**
     * 验证电力设备参数
     */
    private void validateElectricParams(EmsDevice device) {
        // 清空非电力设备字段
        device.setPipeDiameter(null);
        device.setMaxFlowRate(null);
        device.setWorkingPressure(null);
        device.setMaxGasFlow(null);
        device.setWorkingGasPressure(null);
        device.setGasType(null);
    }
    
    /**
     * 验证水力设备参数
     */
    private void validateWaterParams(EmsDevice device) {
        // 清空非水力设备字段
        device.setRatedPower(null);
        device.setRatedVoltage(null);
        device.setRatedCurrent(null);
        device.setMaxGasFlow(null);
        device.setWorkingGasPressure(null);
        device.setGasType(null);
    }
    
    /**
     * 验证燃气设备参数
     */
    private void validateGasParams(EmsDevice device) {
        // 清空非燃气设备字段
        device.setRatedPower(null);
        device.setRatedVoltage(null);
        device.setRatedCurrent(null);
        device.setPipeDiameter(null);
        device.setMaxFlowRate(null);
        device.setWorkingPressure(null);
    }

    /**
     * 生成设备MQTT提交格式
     */
    @Override
    public Map<String, Object> generateMqttFormat(EmsDevice device) {
        Map<String, Object> result = new HashMap<>();

        // MQTT主题
        String topic = "ems/device/" + device.getDeviceCode() + "/data";
        result.put("topic", topic);
        result.put("qos", 1);

        // 设备基本信息
        Map<String, Object> deviceInfo = new HashMap<>();
        deviceInfo.put("deviceName", device.getDeviceName());
        deviceInfo.put("deviceType", device.getDeviceType());
        deviceInfo.put("energyType", getEnergyTypeName(device.getEnergyType()));
        deviceInfo.put("location", device.getLocation());
        deviceInfo.put("manufacturer", device.getManufacturer());
        result.put("deviceInfo", deviceInfo);

        // 根据能源类型生成载荷格式
        Map<String, Object> payload = generatePayloadByEnergyType(device);
        result.put("payload", payload);

        // 字段说明
        Map<String, String> fieldDescriptions = generateFieldDescriptions(device.getEnergyType());
        result.put("fieldDescriptions", fieldDescriptions);

        return result;
    }

    /**
     * 根据能源类型生成载荷格式
     */
    private Map<String, Object> generatePayloadByEnergyType(EmsDevice device) {
        Map<String, Object> payload = new HashMap<>();

        // 公共字段
        payload.put("deviceCode", device.getDeviceCode());
        payload.put("timestamp", System.currentTimeMillis());
        payload.put("energyType", getEnergyTypeCode(device.getEnergyType()));
        payload.put("temperature", 25.3);
        payload.put("status", "0");
        payload.put("quality", "0");
        payload.put("extend1", "设备位置:" + (device.getLocation() != null ? device.getLocation() : ""));
        payload.put("extend2", "设备类型:" + (device.getDeviceType() != null ? device.getDeviceType() : ""));
        payload.put("extend3", "设备名称:" + device.getDeviceName());

        // 根据能源类型添加特定字段
        String energyType = device.getEnergyType();
        if ("1".equals(energyType)) {
            // 电力设备
            payload.put("power", 1250.5);
            payload.put("totalEnergy", 8500.2);
            payload.put("instantEnergy", 125.8);
            payload.put("voltage", 220.5);
            payload.put("current", 5.68);
            payload.put("powerFactor", 0.95);
            payload.put("humidity", 65.2);
        } else if ("2".equals(energyType)) {
            // 水力设备
            payload.put("flowRate", 15.2);
            payload.put("totalFlow", 1250.8);
            payload.put("pressure", 2.5);
        } else if ("3".equals(energyType)) {
            // 燃气设备
            payload.put("flowRate", 8.5);
            payload.put("totalFlow", 680.3);
            payload.put("pressure", 1.8);
        }

        return payload;
    }

    /**
     * 生成字段说明
     */
    private Map<String, String> generateFieldDescriptions(String energyType) {
        Map<String, String> descriptions = new HashMap<>();

        // 公共字段说明
        descriptions.put("deviceCode", "设备编码，与系统中设备编码对应");
        descriptions.put("timestamp", "时间戳，毫秒级Unix时间戳");
        descriptions.put("energyType", "能源类型：electric/water/gas");
        descriptions.put("temperature", "温度，单位：°C");
        descriptions.put("status", "设备状态：0正常 1告警 2故障 3离线");
        descriptions.put("quality", "数据质量：0正常 1异常");
        descriptions.put("extend1", "扩展字段1：设备位置信息");
        descriptions.put("extend2", "扩展字段2：设备类型信息");
        descriptions.put("extend3", "扩展字段3：设备名称信息");

        // 根据能源类型添加特定字段说明
        if ("1".equals(energyType)) {
            descriptions.put("power", "实时功率，单位：kW");
            descriptions.put("totalEnergy", "累计能耗，单位：kWh");
            descriptions.put("instantEnergy", "瞬时能耗，单位：kWh");
            descriptions.put("voltage", "电压，单位：V");
            descriptions.put("current", "电流，单位：A");
            descriptions.put("powerFactor", "功率因数，范围：0-1");
            descriptions.put("humidity", "湿度，单位：%");
        } else if ("2".equals(energyType)) {
            descriptions.put("flowRate", "流量，单位：m³/h");
            descriptions.put("totalFlow", "累计流量，单位：m³");
            descriptions.put("pressure", "压力，单位：Pa");
        } else if ("3".equals(energyType)) {
            descriptions.put("flowRate", "流量，单位：m³/h");
            descriptions.put("totalFlow", "累计流量，单位：m³");
            descriptions.put("pressure", "压力，单位：kPa");
        }

        return descriptions;
    }

    /**
     * 获取能源类型名称
     */
    private String getEnergyTypeName(String energyType) {
        switch (energyType) {
            case "1": return "电力";
            case "2": return "水力";
            case "3": return "燃气";
            default: return "未知";
        }
    }

    /**
     * 获取能源类型代码
     */
    private String getEnergyTypeCode(String energyType) {
        switch (energyType) {
            case "1": return "electric";
            case "2": return "water";
            case "3": return "gas";
            default: return "unknown";
        }
    }
}